package servlet;

import bean.PageBean;
import bean.User;
import bean.UserInfo;
import dao.DealRecordDao;
import dao.DeptMajorDao;
import dao.UserDao;
import dao.UserInfoDao;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import util.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;

import static util.ResponseUtil.*;

/**
 * 骑行用户信息管理
 *
 * @author 邓晴予
 */
@WebServlet(name = "UserServlet", urlPatterns = {"/users", "/user", "/phones"})
public class UserServlet extends HttpServlet {
    private UserDao userDao = new UserDao();
    private DealRecordDao dealRecordDao = new DealRecordDao();
    private DeptMajorDao deptMajorDao = new DeptMajorDao();
    private UserInfoDao userInfoDao = new UserInfoDao();

    /**
     * 骑行用户信息获取
     *
     * @author 邓晴予
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (!"/phones".equalsIgnoreCase(req.getRequestURI())) {
            String startStr = req.getParameter("start");  //当前页
            String pagesizeStr = req.getParameter("pagesize");  //页记录数
            String typeStr = req.getParameter("type");
            String valueStr = req.getParameter("value");
            String prefix = req.getParameter("prefix");

            JsonWrapper result = new JsonWrapper();

            if (null != startStr && null != pagesizeStr) {
//			分页查询
                int start = 0;
                int pagesize = 0;
                List<Object> resultUser;  //查询返回的用户信息

                try {
                    if (!StringUtil.isEmpty(startStr)) {
                        start = Integer.parseInt(startStr);
                    }
                    if (!StringUtil.isEmpty(pagesizeStr)) {
                        pagesize = Integer.parseInt(pagesizeStr);
                    }
                    PageBean pageBean = new PageBean(start, pagesize);
                    resultUser = userDao.userList(pageBean, new User());
                    result.setStatus(200);
                    result.setMsg("success");

                    JSONArray jsonArray = new JSONArray();
                    for (Object object : resultUser) {
                        JSONObject jsonObject = JsonWrapper.parseFromObject(object);
                        jsonArray.add(jsonObject);
                    }
                    result.setDataJsonArray("values", jsonArray);
                } catch (NumberFormatException exp) {
//				查询失败
                    result.setStatus(401);
                    result.setMsg("failed");
                }
            } else if (null != typeStr && null != valueStr) {
//			按条件查询
                User user = new User();
                if ("id".equals(typeStr)) {
                    user.setUserId(valueStr);
                } else if ("username".equals(typeStr)) {
                    user.setUserName(valueStr);
                } else if ("name".equals(typeStr)) {
                    user.setName(valueStr);
                } else if ("cardNumber".equals(typeStr)) {
                    user.setCardNumber(valueStr);
                } else if ("phone".equals(typeStr)) {
                    user.setPhone(valueStr);
                }
                List<Object> resultUser;  //查询返回的用户信息
                resultUser = userDao.userList(null, user);
                result.setStatus(200);
                result.setMsg("success");

                JSONArray jsonArray = new JSONArray();
                for (Object single : resultUser) {
                    JSONObject jsonObject = JsonWrapper.parseFromObject(single);
                    boolean audit = userInfoDao.isAudit(((User) single).getUserId());
                    jsonObject.put("audit", audit);
                    jsonArray.add(jsonObject);
                }
                result.setDataJsonArray("values", jsonArray);
            } else if (null != typeStr && null != prefix) {
//			模糊查询
                User user = new User();
                List<User> resultUser = null;  //查询返回的用户信息
                if ("id".equals(typeStr)) {
                    user.setUserId(prefix);
                    resultUser = userDao.userPrefixSearch(user);
                    result.setStatus(200);
                    result.setMsg("success");

                    JSONArray jsonArray = new JSONArray();
                    for (User aResultUser : resultUser) {
                        JSONObject json = new JSONObject();
                        json.put("value", aResultUser.getUserId());
                        jsonArray.add(json);
                    }
                    result.setDataJsonArray("values", jsonArray);
                } else if ("username".equals(typeStr)) {
                    user.setUserName(prefix);
                    resultUser = userDao.userPrefixSearch(user);
                    result.setStatus(200);
                    result.setMsg("success");

                    JSONArray jsonArray = new JSONArray();
                    for (User aResultUser : resultUser) {
                        JSONObject json = new JSONObject();
                        json.put("value", aResultUser.getUserName());
                        jsonArray.add(json);
                    }
                    result.setDataJsonArray("values", jsonArray);
                } else if ("name".equals(typeStr)) {
                    user.setName(prefix);
                    resultUser = userDao.userPrefixSearch(user);
                    result.setStatus(200);
                    result.setMsg("success");

                    JSONArray jsonArray = new JSONArray();
                    for (User aResultUser : resultUser) {
                        JSONObject json = new JSONObject();
                        json.put("value", aResultUser.getName());
                        jsonArray.add(json);
                    }
                    result.setDataJsonArray("values", jsonArray);
                } else if ("cardNumber".equals(typeStr)) {
                    user.setCardNumber(prefix);
                    resultUser = userDao.userPrefixSearch(user);
                    result.setStatus(200);
                    result.setMsg("success");

                    JSONArray jsonArray = new JSONArray();
                    for (User aResultUser : resultUser) {
                        JSONObject json = new JSONObject();
                        json.put("value", aResultUser.getCardNumber());
                        jsonArray.add(json);
                    }
                    result.setDataJsonArray("values", jsonArray);
                } else if ("phone".equals(typeStr)) {
                    user.setPhone(prefix);
                    resultUser = userDao.userPrefixSearch(user);
                    result.setStatus(200);
                    result.setMsg("success");

                    JSONArray jsonArray = new JSONArray();
                    for (User aResultUser : resultUser) {
                        JSONObject json = new JSONObject();
                        json.put("value", aResultUser.getPhone());
                        jsonArray.add(json);
                    }
                    result.setDataJsonArray("values", jsonArray);
                }
            } else {
//			取总记录数
                try {
                    int total = userDao.userCount(new User());
                    if (total != 0) {
                        result.setMsg("success");
                    } else {
                        result.setMsg("No record!");
                    }
                    result.setStatus(200);
                    result.setDataEntry("total", total);
                } catch (Exception e) {
                    result.setStatus(401);
                    result.setMsg("failed");
                }
            }
            ResponseUtil.write(resp, result.get());
        } else {
            String phone = req.getParameter("p");
            if (!userDao.findByPhone(phone).isPresent()) {
                ResponseUtil.write(resp, 200, "valid phone");
            } else {
                ResponseUtil.write(resp, 301, "invalid phone");
            }
        }
    }

    /**
     * 修改骑行用户信息
     *
     * @author 邓晴予
     */
    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String remoteURI = req.getRequestURI();
        if ("/users".equals(remoteURI)) {
            doAdminPut(req, resp);
        } else if ("/user".equals(remoteURI)) {
            doUserPut(req, resp);
        }
    }

    private void doUserPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        JSONObject json = RequestUtil.getJsonFromRequest(req);
        if (json != null) {
            String phone = (String) json.get("phone");
            String code = (String) json.get("code");
            String newUsername = (String) json.get("newUserName");
            String newPassword = (String) json.get("newPassword");
            String type = (String) json.get("type");
            String userId = (String) json.get("userId");

            JsonWrapper result = new JsonWrapper();

            if (type != null && userId != null) {
                // 挂失与解挂
                String status = (String) json.get("status");
                int tmpStatus = 0;
                switch (type) {
                    case "lock":
                        tmpStatus = -1;
                        break;
                    case "unlock":
                        tmpStatus = 1;
                        break;
                    default:
                }
                if (tmpStatus == 0) {
                    // failed: invalid request
                    ResponseUtil.writeBadRequest(resp);
                    return;
                }
                // check redo
                if (userDao.changeStatus(tmpStatus, userId)) {
                    // success
                    result.setStatus(200);
                    result.setMsg("success");
                } else {
                    // failed: failed to modify
                    result.setStatus(403);
                    result.setMsg("failed");
                }
            } else if (userId != null && newUsername != null) {
                // 设置昵称
                // 前台骑行用户修改个人信息
                User user = new User();
                user.setUserId(userId);
                user.setUserName(json.getString("newUserName"));
                try {
                    int updateNum = userDao.userModify(user);
                    if (updateNum == 1) {
                        result.setStatus(200);
                        result.setMsg("success");
                    } else {
                        result.setStatus(403);
                        result.setMsg("failed");
                    }
                } catch (Exception e) {
                    result.setStatus(403);
                    result.setMsg("failed");
                }
            } else if (phone != null && code != null && newPassword != null) {
                //			重置密码
                //			短信验证码验证
                int isSuccess = SMSUtils.checkSMSCode(req, resp, phone, code);
                if (SMSUtils.CHECK_RESULT_FALSE == isSuccess) {
                    //				验证码不正确
                    result.setStatus(301);
                    result.setMsg("failed");
                } else if (SMSUtils.CHECK_RESULT_INVALID == isSuccess) {
                    //				验证码失效
                    result.setStatus(302);
                    result.setMsg("failed");
                } else {
                    if (userDao.changePassword(newPassword, phone)) {
                        result.setStatus(200);
                        result.setMsg("success");
                    } else {
                        result.setStatus(403);
                        result.setMsg("failed");
                    }
                }
            }
            ResponseUtil.write(resp, result.get());
        }
    }

    private void doAdminPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String t = req.getParameter("t");
        // 后台管理员修改骑行用户信息
        JSONObject json = RequestUtil.getJsonFromRequest(req);
        if ("profile".equals(t)) {
            if (json != null) {
                User user = new User();
                String userId = json.getString("userId");
                user.setUserId(userId);

                String name = json.getString("name");
                user.setName(name);

                String cardNumber = json.getString("cardNumber");
                user.setCardNumber(cardNumber);

                String score = json.getString("score");
                user.setScore(score);

                String phone = json.getString("phone");
                user.setPhone(phone);

                String status = json.getString("status");
                user.setStatus(status);

                String balance = json.getString("balance");
                user.setBalance(balance);

                try {
                    boolean finish = userDao.userModify(user) > 0;
                    if (finish) {
                        writeSuccess(resp);
                    } else {
                        writeNotModified(resp);
                    }
                } catch (Exception e) {
                    writeInternalError(resp);
                }
            } else {
                writeBadRequest(resp);
            }
        } else if ("recharge".equals(t)) {
            if (json != null) {
                String type = json.getString("type");
                String typeValue = json.getString("typeValue");
                String money = json.getString("money");
                try {
                    switch (type) {
                        case "username":
                            rechargeByUsername(typeValue, money);
                            break;
                        case "phone":
                            rechargeByPhone(typeValue, money);
                            break;
                        default:
                            writeBadRequest(resp);
                    }
                    writeSuccess(resp);
                } catch (SQLException e) {
                    writeInternalError(resp);
                }
            } else {
                writeBadRequest(resp);
            }
        } else {
            writeBadRequest(resp);
        }
    }

    private void rechargeByUsername(String username, String money) throws SQLException {
        Connection conn = JdbcUtils.createConnection();
        try {
            conn.setAutoCommit(false);
            Optional<User> ou = userDao.findByUsername(username);
            if (ou.isPresent()) {
                BigDecimal m = BigDecimal.valueOf(Long.parseLong(money));
                recharge(conn, ou.get(), m);
                conn.commit();
            }
        } catch (SQLException e) {
            conn.rollback();
        } finally {
            conn.close();
        }
    }

    private void rechargeByPhone(String phone, String money) throws SQLException {
        Connection conn = JdbcUtils.createConnection();
        try {
            conn.setAutoCommit(false);
            Optional<User> ou = userDao.findByPhone(phone);
            if (ou.isPresent()) {
                BigDecimal m = BigDecimal.valueOf(Long.parseLong(money));
                recharge(conn, ou.get(), m);
                conn.commit();
            }
        } catch (SQLException e) {
            e.printStackTrace();
            conn.rollback();
        } finally {
            conn.close();
        }
    }

    private void recharge(Connection conn, User user, BigDecimal m) throws SQLException {
        dealRecordDao.recharge(conn, user, m);
        userDao.recharge(conn, user, m);
    }

    /**
     * 骑行用户信息删除
     *
     * @author 邓晴予
     */
    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        JsonWrapper result = new JsonWrapper();
        try {
            userDao.userDelete(req.getParameter("id"));
            result.setStatus(200);
            result.setMsg("success");
        } catch (Exception e) {
            result.setStatus(401);
            result.setMsg("failed");
        }
        ResponseUtil.write(resp, result);
    }

    /**
     * 骑行用户信息添加
     *
     * @author 邓晴予
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String remoteURI = req.getRequestURI();
        if ("/users".equals(remoteURI)) {
            doAdminPost(req, resp);
        } else if ("/user".equals(remoteURI)) {
            doUserPost(req, resp);
        }
    }

    private void doAdminPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        JSONObject json = RequestUtil.getJsonFromRequest(req);
        if (json != null) {
            User user = new User();
            user.setUserName(json.getString("username"));
            user.setPassword(json.getString("password"));
            user.setName(json.getString("name"));
            user.setPhone(json.getString("phone"));
            user.setStatus("1");

            boolean needCard = json.getBoolean("needCard");
            UserInfo ui = new UserInfo();
            int uiid;
            if (needCard) {
                user.setCardNumber((String) json.get("cardNumber"));
                user.setBalance((String) json.get("balance"));
                user.setScore((String) json.get("balance"));
                ui.setName(json.getString("name"));
//        ui.setSchool((String) json.get("school"));
                ui.setSchool("郑州大学");
                ui.setStuId((String) json.get("stuId"));
                ui.setMajor((String) json.get("major"));
                try {
                    uiid = userInfoDao.insertWithId(ui);
                    user.setUserInfoId(String.valueOf(uiid));
                } catch (SQLException e) {
                    e.printStackTrace();
                    writeInternalError(resp);
                    return;
                }
            } else {
                user.setBalance("0");
                user.setScore("0");
            }
            // 认证
            try {
                boolean finish = userDao.userAdd(user);
                if (finish) {
                    writeSuccess(resp);
                } else {
                    writeNotModified(resp);
                }
            } catch (Exception e) {
                writeInternalError(resp);
            }
        } else {
            writeBadRequest(resp);
        }
    }

    private void doUserPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        String type = req.getParameter("type");
        JsonWrapper result = new JsonWrapper();

        if ("authentication".equals(type)) {
//			骑行用户身份验证
            String dept = req.getParameter("department");
            String major = req.getParameter("major");
            boolean isMajorBelongDept = deptMajorDao.isMajorBelongDept(major, dept);
            if (isMajorBelongDept) {
//				专业属于院系
                try {
                    int userCount = userDao.userCount(new User(req.getParameter("userId")));
                    if (userCount == 1) {
//						用户信息存在
                        UserInfo userInfo = new UserInfo();
                        userInfo.setStuId(req.getParameter("studentNumber"));
                        userInfo.setName(req.getParameter("name"));
                        userInfo.setSchool(req.getParameter("school"));
                        userInfo.setMajor(major);
                        boolean isSuccess = userInfoDao.insertUserInfo(userInfo);
                        if (isSuccess) {
//							用户身份保存成功
                            result.setStatus(200);
                            result.setMsg("success");
                        } else {
//							用户身份信息保存失败
                            result.setStatus(400);
                            result.setMsg("failed");
                        }
                    } else {
//						用户信息不存在
                        result.setStatus(400);
                        result.setMsg("failed");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    result.setStatus(401);
                    result.setMsg("failed");
                }
            } else {
//				专业不属于院系
                result.setStatus(400);
                result.setMsg("failed");
            }
        } else {
//			骑行用户信息添加
            User user = new User();
            user.setUserId(req.getParameter("id"));
            user.setUserName(req.getParameter("userName"));
            user.setPassword(req.getParameter("password"));
            user.setName(req.getParameter("name"));
            user.setCardNumber(req.getParameter("cardNumber"));
            user.setScore(req.getParameter("score"));
            user.setPhone(req.getParameter("phone"));
            user.setStatus(req.getParameter("status"));
            user.setBalance(req.getParameter("balance"));

            try {
                boolean success = userDao.userAdd(user);
                if (success) {
                    result.setStatus(200);
                    result.setMsg("success");
                } else {
                    result.setStatus(401);
                    result.setMsg("failed");
                }
            } catch (Exception e) {
                result.setStatus(401);
                result.setMsg("failed");
            }
        }
        ResponseUtil.write(resp, result);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        super.service(req, resp);
    }
}
